package de.micromata.icalour;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Locale;
import java.util.Random;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.plugins.jpeg.JPEGImageWriteParam;
import javax.imageio.stream.ImageOutputStream;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.fortuna.ical4j.model.Calendar;

import org.apache.log4j.Logger;

/**
 * The servlet imports events from iCalendar file and call some methods for
 * preparing and printing the data.
 * Send image to client as outputstream or save image as file (this option can be set in the RssServlet)
 */
public class ImageServlet extends HttpServlet {

	private static final long serialVersionUID = 1781718579371045471L;
	private static Logger LOG = Logger.getRootLogger();
	private String absoluteFilesystemPath = null;
	private int cacheTime;
	private byte [] imageByteArray = null;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public ImageServlet() {
        super();
    }
    
	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		boolean saveImageFile = false;
		String imageFile = null;
		
		// check the output mode: 
		if (request.getParameter("dynamic") != null && request.getParameter("dynamic").equals("off")) {
			saveImageFile = true;
			imageFile = request.getParameter("file");
		}
		
		// check if caching turned off
		String cacheParam = request.getParameter("cache");
		if (cacheParam != null && cacheParam.equals("off")) {
			cacheTime = -1;
		}
		
		// set header information
		if (saveImageFile) {
			response.setContentType("image/jpeg");
		}
		
		response.setHeader("Cache-Control","no-cache"); //HTTP 1.1
		response.setHeader("Pragma","no-cache"); //HTTP 1.0
		response.setDateHeader ("Expires", 0); //prevents caching at the proxy server
		
		java.util.Calendar now = java.util.Calendar.getInstance();
		now.set(java.util.Calendar.HOUR_OF_DAY, now.get(java.util.Calendar.HOUR_OF_DAY));
		if (now.get(java.util.Calendar.MINUTE) != cacheTime) {
			cacheTime = now.get(java.util.Calendar.MINUTE);
			LOG.info("image port: "+request.getServerPort());
			absoluteFilesystemPath = getServletContext().getRealPath("/");
			

			// Get the environment entries from context.xml
			Context env = null;
			boolean remoteFile = false;
			String calendarFile = null;
			try {
				env = (Context)new InitialContext().lookup("java:comp/env");
				remoteFile = ((String)env.lookup("remoteFile")).equals("yes") ? true : false;
				calendarFile = (String)env.lookup("calendarFile");
			} catch (NamingException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			Calendar calendar = Utils.openIcal(calendarFile, remoteFile); // remote calendar file
			//Calendar calendar = Utils.openIcal(absoluteFilesystemPath + "cal.ics", false); // local calendar file
			
			// open random template image or empty image
			//BufferedImage outImg = new BufferedImage(800, 480, 1); // empty image
			Random r = new Random();
			int random = r.nextInt(7) + 1;
			String filename = "img/template"+random+".png";
	
			BufferedImage bufferImg = null;
			try {
				bufferImg = ImageIO.read(new File(absoluteFilesystemPath+filename));
			} catch (IOException e2) {
				LOG.error("could not open template image: "+absoluteFilesystemPath+filename);
				e2.printStackTrace();
			}
			
			DigitalFrame w820 = new DigitalFrame(calendar); // create and set the content/data
			Drawing.drawContent(bufferImg, w820, absoluteFilesystemPath); // generate/draw image
			
			// set image format and quality settings
			ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
			ImageWriter writer = ImageIO.getImageWritersByFormatName("jpg").next();
			ImageOutputStream ios = ImageIO.createImageOutputStream(byteOutputStream);
			writer.setOutput(ios);
			ImageWriteParam iwparam = new JPEGImageWriteParam(Locale.getDefault());
			iwparam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
			iwparam.setCompressionQuality(1f);
			writer.write(null, new IIOImage(bufferImg, null, null), iwparam);
			ios.flush();
			ios.close();
	
			if (!saveImageFile) {
				// save a jpeg file on the file system
				imageByteArray = byteOutputStream.toByteArray();
		    OutputStream os = response.getOutputStream();
		    os.write(imageByteArray);
			} else {
				// send data stream to the client without saving a image on the file system
				IIOImage iio = new IIOImage(bufferImg, null, null);
				if (imageFile == null || imageFile.equals("")) {
					imageFile = "image.jpg";
				}
		    writer.setOutput(ImageIO.createImageOutputStream(new File(absoluteFilesystemPath + imageFile)));
		    writer.write(null, iio, iwparam); 
			}
			writer.dispose();
	    
	    
		} else {
			LOG.info("send cached or already generated image "+ cacheTime +": "+request.getServerPort());
			OutputStream os = response.getOutputStream();
			if (!saveImageFile) {
				os.write(imageByteArray);
			}
		}
	}


	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	}

}
